package model

import (
	"database/sql/driver"
	"engine/consts"
	"errors"
	"fmt"
	"github.com/goccy/go-json"
	"gorm.io/datatypes"
	"time"
)

type AgencyUserLog struct {
	Id         uint64            `gorm:"column:id;type:bigint(20) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
	UserId     uint64            `gorm:"column:user_id;type:bigint(20) unsigned" json:"userId"`
	AgencyId   uint64            `gorm:"column:agency_id;type:bigint(20) unsigned;NOT NULL" json:"agencyId"`
	ActionName consts.ActionName `gorm:"column:action_name;type:varchar(255)" json:"actionName"`
	Ip         string            `gorm:"column:ip;type:varchar(128);NOT NULL" json:"ip"`
	Action     *UserAction       `gorm:"column:action;type:json" json:"action"`
	CreatedAt  time.Time         `gorm:"column:created_at;type:timestamp;NOT NULL" json:"createdAt" swaggertype:"string"`
	UpdatedAt  *time.Time        `gorm:"column:updated_at;type:timestamp" json:"updatedAt" swaggertype:"string" extensions:"x-nullable"`
	UserName   string            `gorm:"user_name" json:"userName"`
}

func (*AgencyUserLog) TableName() string {
	return "agency_user_logs"
}

type SysUserLog struct {
	Id         uint64            `gorm:"column:id;type:bigint(20) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
	UserId     uint64            `gorm:"column:user_id;type:bigint(20) unsigned" json:"userId"`
	ActionName consts.ActionName `gorm:"column:action_name;type:varchar(255)" json:"actionName"`
	Ip         string            `gorm:"column:ip;type:varchar(128);NOT NULL" json:"ip"`
	Action     *UserAction       `gorm:"column:action;type:json" json:"action"`
	CreatedAt  time.Time         `gorm:"column:created_at;type:timestamp;default:CURRENT_TIMESTAMP;NOT NULL" json:"createdAt"`
	UpdatedAt  *time.Time        `gorm:"column:updated_at;type:timestamp" json:"updatedAt"`
	UserName   string            `gorm:"user_name" json:"userName"`
}

func (*SysUserLog) TableName() string {
	return "sys_user_logs"
}

type SupplierUserLog struct {
	Id         uint64            `gorm:"column:id;type:bigint(20) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
	UserId     uint64            `gorm:"column:user_id;type:bigint(20) unsigned" json:"userId"`
	SupplierId uint64            `gorm:"column:supplier_id;type:bigint(20) unsigned;NOT NULL" json:"supplierId"`
	ActionName consts.ActionName `gorm:"column:action_name;type:varchar(255)" json:"actionName"`
	Ip         string            `gorm:"column:ip;type:varchar(128);NOT NULL" json:"ip"`
	Action     *UserAction       `gorm:"column:action;type:json" json:"action"`
	CreatedAt  time.Time         `gorm:"column:created_at;type:timestamp;default:CURRENT_TIMESTAMP;NOT NULL" json:"createdAt"`
	UpdatedAt  *time.Time        `gorm:"column:updated_at;type:timestamp" json:"updatedAt"`
	UserName   string            `gorm:"user_name" json:"userName"`
}

func (*SupplierUserLog) TableName() string {
	return "supplier_user_logs"
}

type UserAction struct {
	RelatedSource   string          `json:"relatedSource,omitempty"`
	RelatedSourceId string          `json:"relatedSourceId,omitempty"`
	ChangedContent  []ChangeContent `json:"changedContent,omitempty"`
}

func (c *UserAction) Value() (driver.Value, error) {
	b, err := json.Marshal(c)
	return string(b), err
}

func (c *UserAction) Scan(value interface{}) error {
	bytes, ok := value.([]byte)
	if !ok {
		return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
	}
	err := json.Unmarshal(bytes, &c)
	if err != nil {
		fmt.Println(err)
	}
	return nil
}

type ChangeContent struct {
	PropertyName string         `json:"propertyName"`
	BeforeValue  datatypes.JSON `json:"beforeValue"`
	AfterValue   datatypes.JSON `json:"afterValue"`
}

func (c *ChangeContent) Value() (driver.Value, error) {
	b, err := json.Marshal(c)
	return string(b), err
}

func (c *ChangeContent) Scan(value interface{}) error {
	bytes, ok := value.([]byte)
	if !ok {
		return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
	}
	err := json.Unmarshal(bytes, &c)
	if err != nil {
		fmt.Println(err)
	}
	return nil
}
